home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlb20 / lib / ftw.c < prev    next >
C/C++ Source or Header  |  1992-02-11  |  3KB  |  111 lines

  1. /*
  2. **  FTW
  3. **  Walk a directory hierarchy from a given point, calling a user-supplied
  4. **  function at each thing we find.  If we go below a specified depth,
  5. **  recycle file descriptors.
  6. */
  7.  
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <stdlib.h>
  11. #include <sys/types.h>
  12. #include <sys/stat.h>
  13. #include <sys/dir.h>
  14. #include <ftw.h>
  15.  
  16. #define EQ(a, b)    (strcmp((a), (b)) == 0)
  17.  
  18. int
  19. ftw(directory, funcptr, depth)
  20.     char         *directory;
  21.     int            (*funcptr)();
  22.     int              depth;
  23. {
  24.     register DIR     *dirp;
  25.     struct direct     *entp;
  26.     struct stat          stats;
  27.     register char     *p;
  28.     register int      i;
  29. #ifndef __MINT__
  30.     long          seekpoint;
  31. #endif
  32.     char         *fullpath;
  33.  
  34. #ifndef __MINT__
  35.     seekpoint = 0;    /* avoid spurious warning from gcc -Wall */
  36. #endif
  37.  
  38.     /* If can't stat, tell the user so. */
  39.     if (stat(directory, &stats) < 0)
  40.     return (*funcptr)(directory, &stats, FTW_NS);
  41.  
  42.     /* If it's not a directory, call the user's function. */
  43.     if ((stats.st_mode & S_IFMT) != S_IFDIR)
  44.     /* Saying "FTW_F" here is lying; what if this is a symlink? */
  45.     return (*funcptr)(directory, &stats, FTW_F);
  46.  
  47.     /* Open directory; if we can't, tell the user so. */
  48.     dirp = opendir(directory);
  49.     if (dirp == NULL)
  50.     return (*funcptr)(directory, &stats, FTW_DNR);
  51.  
  52.     /* See if user wants to go further. */
  53.     i = (*funcptr)(directory, &stats, FTW_D);
  54.     if (i) {
  55.     closedir(dirp);
  56.     return i;
  57.     }
  58.  
  59.     /* Get ready to hold the full paths. */
  60.     i = strlen(directory);
  61.     fullpath = (char *) malloc( (size_t) (i + 1 + MAXNAMLEN + 1) );
  62.     if (fullpath == NULL) {
  63.     closedir(dirp);
  64.     return -1;
  65.     }
  66.     (void)strcpy(fullpath, directory);
  67.     p = &fullpath[i];
  68.     if (i && p[-1] != '/')
  69.     *p++ = '/';
  70.  
  71.     /* Read all entries in the directory.. */
  72.     while (entp = readdir(dirp))
  73.     if (!EQ(entp->d_name, ".") && !EQ(entp->d_name, "..")) {
  74. #ifndef __MINT__
  75.         if (depth <= 1) {
  76.         /* Going too deep; checkpoint and close this directory. */
  77.         seekpoint = telldir(dirp);
  78.         closedir(dirp);
  79.         dirp = NULL;
  80.         }
  81. #endif
  82.         /* Process the file. */
  83.         (void)strcpy(p, entp->d_name);
  84.         i = ftw(fullpath, funcptr, depth - 1);
  85.         if (i) {
  86.         /* User's finished; clean up. */
  87.         free(fullpath);
  88.         if (dirp)
  89.             closedir(dirp);
  90.         return i;
  91.         }
  92.  
  93. #ifndef __MINT__
  94.         /* Reopen the directory if necessary. */
  95.         if (dirp == NULL) {
  96.         dirp = opendir(directory);
  97.         if (dirp == NULL) {
  98.             free(fullpath);
  99.             return -1;
  100.         }
  101.         seekdir(dirp, seekpoint);
  102.         }
  103. #endif
  104.     }
  105.  
  106.     /* Clean up. */
  107.     free(fullpath);
  108.     closedir(dirp);
  109.     return 0;
  110. }
  111.